﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using Me.Prettyprint.Cassandra.Utils;

namespace Me.Prettyprint.Cassandra.Service
{
    /// <summary>
    /// The default implementation for a single host in a Cassandra cluster.
    /// It has a default port of 9160 and max active connection of 50.
    /// </summary>
    public class CassandraHost
    {
        public Logger logger = new Logger(typeof(CassandraHost));
        public const int DEFAULT_PORT = 9160;
        public const int DEFAULT_MAX_ACTIVE = 50;
        public const bool DEFAULT_USE_FRAMED_THRIFT_TRANSPORT = true;
        public const int DEFAULT_MAX_FRAME_SIZE = 0x7FFFFFFF;
        public const long DEFAULT_MAX_WAITTIME_WHEN_EXHAUSTED = -1;
        public const bool DEFAULT_LIFO = true;
        public const long DEFAULT_MAX_CONNECT_TIME = -1;
        public const long DEFAULT_MAX_LAST_SUCCESS_TIME = -1;

        public CassandraHost(string url)
            : this(url, ParsePortFromUrl(url))
        {
        }

        public CassandraHost(string url2, int port)
        {
            MaxFrameSize = DEFAULT_MAX_FRAME_SIZE;
            MaxActive = DEFAULT_MAX_ACTIVE;
            UseThriftFramedTransport = DEFAULT_USE_FRAMED_THRIFT_TRANSPORT;
            Lifo = DEFAULT_LIFO;
            MaxLastSuccessTimeMillis = DEFAULT_MAX_LAST_SUCCESS_TIME;
            MaxConnectTimeMillis = DEFAULT_MAX_CONNECT_TIME;
            url2 = ParseHostFromUrl(url2);
            Port = port;
            StringBuilder b = new StringBuilder();
            IPAddress[] address;
            string turl, tip;
            try
            {
                address = Dns.GetHostAddresses(url2);
                turl = url2;
                tip = address[0].ToString();
            }
            catch (Exception e)
            {
                logger.Error(string.Format("Unable to resolve host {0}, {1}", url2, e));
                turl = url2;
                tip = url2;
            }
            Host = turl;
            Ip = tip;
            b.Append(url2);
            b.Append("(");
            b.Append(Ip);
            b.Append("):");
            b.Append(port);
            Name = b.ToString();
            Url = string.Format("%s:%d", Host, Port);
        }
        public string Url
        {
            get;
            set;
        }
        public string Name
        {
            get;
            set;
        }
        public string Host
        {
            get;
            set;
        }
        public String Ip
        {
            get;
            set;
        }
        public int Port
        {
            get;
            set;
        }
        public override bool Equals(Object obj)
        {
            if (!(obj is CassandraHost))
            {
                return false;
            }
            CassandraHost other = (CassandraHost)obj;
            return other.Ip.Equals(Ip) && other.Port == Port;
        }
        public override int GetHashCode()
        {
            return Ip.GetHashCode();
        }
        public int MaxActive
        {
            get;
            set;
        }
        public long MaxWaitTimeWhenExhausted
        {
            get;
            set;
        }
        public int CassandraThriftSocketTimeout
        {
            get;
            set;
        }
        public bool UseThriftFramedTransport
        {
            get;
            set;
        }
        public int MaxFrameSize
        {
            get;
            set;
        }
        public static string ParseHostFromUrl(String urlPort)
        {
            return urlPort.LastIndexOf(':') > 0 ? urlPort.Substring(0, urlPort.LastIndexOf(':')) : urlPort;
        }
        public static int ParsePortFromUrl(string urlPort)
        {
            return urlPort.LastIndexOf(':') > 0 ? Int32.Parse(urlPort.Substring(urlPort.LastIndexOf(':') + 1, urlPort.Length)) : DEFAULT_PORT;
        }
        public bool Lifo
        {
            get;
            set;
        }
        public bool UseSocketKeepalive
        {
            get;
            set;
        }
        public long MaxConnectTimeMillis
        {
            get;
            set;
        }
        public long MaxLastSuccessTimeMillis
        {
            get;
            set;
        }
    }
}
